﻿namespace Player.Models
{
    using System;
    using System.Collections.Generic;

    using Common.Protocol;

    public class MainViewModel
    {
        public static float Interval = 0.01f;

        public List<ProtocolInterval> Intervals;

        public Dictionary<string, double> CurrentValues;

        public ProtocolInterval currentInterval;

        public long TotalMilliseconds;

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public DateTime CurrentTime { get; private set; }

        public MainViewModel()
        {
            this.Start = Reader.BlockHeaders[0].Start;
            this.GetChannelsValues();
        }

        private void GetChannelsValues()
        {
            this.Intervals = new List<ProtocolInterval>();
            int currentHeaderNumber = 0;

            for (int i = 0; i < Reader.BlockHeaders.Count; i++)
            {
                if (Reader.BlockHeaders[i].Start <= this.Start && Reader.BlockHeaders[i].End > this.Start)
                {
                    currentHeaderNumber = i;
                    break;
                }
            }
            
            long millisecondsToRead = (long)(MainViewModel.Interval * 3600000);
            long millisecondsRead = 0;
            this.TotalMilliseconds = 0;
            DateTime timeToRead;

            while (true)
            {
                ProtocolInterval interval = new ProtocolInterval();
                interval.Header = Reader.BlockHeaders[currentHeaderNumber];
                timeToRead = interval.Header.Start;

                for (int channelId = 0; channelId < Reader.BlockHeaders[currentHeaderNumber].Channels.Count; channelId++)
                {
                    ChannelInterval channelInterval = new ChannelInterval(
                        Reader.BlockHeaders[currentHeaderNumber].Start,
                        timeToRead,
                        Reader.BlockHeaders[currentHeaderNumber].Channels[channelId]);

                    millisecondsRead = 0;
                    timeToRead = Reader.BlockHeaders[currentHeaderNumber].Start;
                    int regPeriod = Reader.BlockHeaders[currentHeaderNumber].Channels[channelId].RegPeriod;

                    while (millisecondsRead < millisecondsToRead
                        && timeToRead <= Reader.BlockHeaders[currentHeaderNumber].End)
                    {
                        channelInterval.Values.Add(Reader.GetChannelValue(channelId, timeToRead, Reader.BlockHeaders[currentHeaderNumber].BlockId));
                        channelInterval.End = timeToRead;

                        millisecondsRead += regPeriod;
                        timeToRead = timeToRead.AddMilliseconds(regPeriod);

                        if (channelId == 0)
                        {
                            this.TotalMilliseconds += regPeriod;
                        }
                    }

                    interval.ChannelIntervals.Add(channelInterval);
                }

                this.Intervals.Add(interval);

                if (++currentHeaderNumber >= Reader.BlockHeaders.Count || this.TotalMilliseconds >= millisecondsToRead)
                {
                    this.CalculateCurrentTimeValues();
                    return;
                }
            }
        }

        private void CalculateCurrentTimeValues()
        {
            long intervalMilliseconds = this.TotalMilliseconds / 2;
            this.currentInterval = new ProtocolInterval();
            foreach (var interval in this.Intervals)
            {
                intervalMilliseconds -=
                    (long)(interval.ChannelIntervals[0].End - interval.ChannelIntervals[0].Start).TotalMilliseconds;
                if (intervalMilliseconds <= 0)
                {
                    this.currentInterval = interval;
                    break;
                }
            }

            intervalMilliseconds += (long)(this.currentInterval.ChannelIntervals[0].End
                - this.currentInterval.ChannelIntervals[0].Start).TotalMilliseconds;
            this.CurrentTime = this.currentInterval.ChannelIntervals[0].Start.AddMilliseconds(intervalMilliseconds);

            this.CurrentValues = new Dictionary<string, double>();
            for (int id = 0; id < this.currentInterval.ChannelIntervals.Count; id++)
            {
                string channelName = this.currentInterval.ChannelIntervals[id].Config.Name;
                float value = Reader.GetChannelValue(id, this.CurrentTime, this.currentInterval.Header.BlockId);
                this.CurrentValues.Add(channelName, value);
            }
        }
    }
}